"""
!/usr/bin/env python
-*- coding: utf-8 -*-
@Author  : MarkJia
@Site    :
@File    : 14、高级控件的使用：鼠标和键盘操作.py
"""
import sys

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains
# from selenium.webdriver import TouchActions
from selenium.webdriver.common.keys import Keys

#  ==================  高级控件的使用场景  ===============================
"""
复制粘贴 ： 键盘事件
拖动元素到某个位置： 鼠标事件
鼠标悬停： 鼠标事件
滚动到某个元素： 滚动事件
使用触控笔点击： 触控笔事件（了解即可）

ActionChains 解析：
    ActionChains(self.driver).操作.perform()
    实例化类 ActionChains ，参数为 driver 实例
    中间可以有多个操作
    .perform()代表确定执行

键盘事件：
    按下，释放键盘键位
    结合 send_keys 回车
    复制，粘贴(ctrl c , ctrl v)
"""


# =================   键盘事件 - 使用 shift 实现大写 =============================
class TestKeyBoardDemo:
    def setup_class(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(3)

    def teardown_class(self):
        self.driver.quit()

    def test_key_down_up(self):
        """
        ActionChains(self.driver):实例化 ActionChains 类
        ===================         key_down(Keys.SHIFT,ele) : 按下 shift 键实现大写  ===================================
        send_keys("selenium") : 输入大写的 selenium
        perform() : 确定执行
        """
        # 1. 访问测试人网站
        self.driver.get('https://ceshiren.com')
        # 2. 点击搜索按钮
        self.driver.find_element(By.ID, "search-button").click()
        # 正常情况下
        # self.driver.find_element(By.ID, "search-term").send_keys("selenium")
        # 3. 输入搜索的内容，输入的同时按住 shift 键
        ele = self.driver.find_element(By.ID, "search-term")  # 目标元素
        # key_down 表示按下某个键位   Keys 表示键盘输入
        ActionChains(self.driver) \
            .key_down(Keys.SHIFT, ele) \
            .send_keys("selenium") \
            .perform()


#  ============================= 键盘事件 - 输入后回车  =====================================================
class TestKeyBoardDemo1:
    def setup_class(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(3)

    def teardown_class(self):
        self.driver.quit()

    def test_enter(self):
        self.driver.get('https://www.sogou.com/')
        ele = self.driver.find_element(By.ID, "query")
        ele.send_keys("selenium")
        # 第一种方式
        ele.send_keys(Keys.ENTER)
        # 第二种方式
        # key_down 表示按下某个键位   Keys 表示键盘输入
        ActionChains(self.driver) \
            .key_down(Keys.ENTER) \
            .perform()

    #  ========================================    键盘事件 - 复制粘贴   =================================
    """
    多系统兼容
        mac 的复制按钮为 COMMAND
        windows 的复制按钮为 CONTROL
    左箭头：keys.ARROW_LEFT
    按下 COMMAND 或者 CONTROL ： key_down(cmd_ctrl)
    按下剪切与粘贴按钮： send_keys('xvvvv')

    """

    def test_copy_and_paste(self):
        self.driver.get('https://ceshiren.com')
        self.driver.find_element(By.ID, "search-button").click()
        ele = self.driver.find_element(By.ID, "search-term")
        #  ==================  判断操作系统是否为 mac ，如果是 mac，则返回 command 。如果 是 windows ，返回 control 键位 =====================
        command_control = Keys.COMMAND if sys.platform == "darwin" else Keys.CONTROL
        ActionChains(self.driver) \
            .key_down(Keys.SHIFT, ele) \
            .send_keys("selenium!") \
            .key_down(Keys.ARROW_LEFT) \
            .key_down(command_control) \
            .send_keys("xvv") \
            .key_up(command_control) \
            .perform()


"""
鼠标事件：
    双击
    拖动元素
    指定位置（悬浮）
    
"""


#  =============================  鼠标事件 - 双击 ============================================
# ==============================  double_click(元素对象) ： 双击元素  ==================================

class TestMouseDemo:

    def setup_class(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(3)

    def teardown_class(self):
        self.driver.quit()

    def test_double_click(self):
        self.driver.get('https://vip.ceshiren.com/#/ui_study')
        ele = self.driver.find_element(By.ID, "primary_btn")
        # 调用双击方法，传入被双击的元素
        ActionChains(self.driver).double_click(ele).perform()
        time.sleep(2)


# ============================= 鼠标事件 - 拖动元素 =========================================
# ============================== drag_and_drop(起始元素对象，结束元素对象)：拖动并放开元素  ============================
class TestMouseDemo1:

    def setup_class(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(3)

    def teardown_class(self):
        self.driver.quit()

    def test_drag_and_drop(self):
        self.driver.get('https://vip.ceshiren.com/#/ui_study/action_chains')
        # 获取起始元素
        start_ele = self.driver.find_element(By.CSS_SELECTOR, ".item1")
        # 获取目标元素
        target_ele = self.driver.find_element(By.CSS_SELECTOR, ".item3")
        ActionChains(self.driver).drag_and_drop(start_ele, target_ele).perform()


# ============================= 鼠标事件 - 鼠标悬浮 ====================================================
# ===================== move_to_element(元素对象)：移动到某个元素 ===============================
class TestMouseDemo2:

    def setup_class(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(3)

    def teardown_class(self):
        self.driver.quit()

    #   =========================     按住 ctrl + shift + c ，展开下拉框（定位元素很方便） 或者 点击源代码后暂停 ===========================
    def test_move_element(self):
        self.driver.get("https://vip.ceshiren.com/#/ui_study/action_chains2")
        time.sleep(2)
        ele = self.driver.find_element(By.CSS_SELECTOR, ".menu")
        ActionChains(self.driver).move_to_element(ele).perform()
        # 常用
        self.driver.find_element(By.XPATH, "//*[contains(text(),'就业班')]").click()
        time.sleep(5)


# ============================ 滚轮/滚动操作 ========================================
# ========================= scroll_to_element(WebElement对象)：滚动到某个元素 ===============================

"""
滚动到元素
根据坐标滚动
注意： selenium 版本(需要在 4.2 之后)
"""


class TestScrollDemo:

    def setup_class(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(3)

    def teardown_class(self):
        self.driver.quit()

    def test_scroll_to_element(self):
        self.driver.get('https://ceshiren.com')
        time.sleep(3)
        ele = self.driver.find_element(By.XPATH, "//*[text()='jq命令的使用']")
        ActionChains(self.driver).scroll_to_element(ele).perform()
        time.sleep(5)

    #  ==================   根据坐标滚动: scroll_by_amount(横坐标，纵坐标)   =====================
    def test_scroll_to_amount(self):
        self.driver.get('https://ceshiren.com')
        ActionChains(self.driver).scroll_by_amount(0, 10000).perform()
        time.sleep(5)


# 常用定位操作事件：右击、页面滑动、表单操作
# TouchAction：执行PC端和移动端的点击、拖拽、多点触控、以及模拟手势的各种操作
#  =====================  ActionChains：执行PC端的鼠标点击、右击、双击、拖拽等  ============================
import time

"""
执行原理：
调用 Actionchains 方法时，不会立即执行。而是将所有的操作，按顺序存放在一个队列里，当你调用 perform（） 方法时，队列中的事件会依次执行
1、生成一个动作：action = ActionChains(driver)
2、动作添加方法：action.方法
3、调用perform()方法执行，action.perform()

2、常用事件操作方法有：
链式调用：
ActionChains(driver).move_to_element(element).click(element).perform()

分布写法：
action = Actionchains(driver)
单击：action.click(element) 
右击：action.context_click(element)
双击：action.double_click(element)
移动到某一个元素：action.move_to_element(element)
拖拽某一个元素然后松开：action.drag_and_drop(source_element,target_element)  (起始元素，终止元素)
执行链中的所有动作：action.perform()



ActionChains()模拟键盘按键方法
action = ActionChains()
action.send_keys(Keys.BACK_SPACE)
action.perform()
"""

from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
ele = (By.ID, 'kw')
ele2 = (By.ID, 'su')

# 常规写法
action = ActionChains(driver)
action.move_to_element(ele)
action.click(ele2)
action.perform()

# 链式调用
ActionChains(driver).move_to_element(ele).click(ele2).perform()


class TestActionChains:

    def setup(self):
        self.driver = webdriver.Chrome()
        self.driver.maximize_window()
        self.driver.implicitly_wait(10)

    def teardown(self):
        self.driver.quit()

    # 鼠标单击、右击、双击操作
    def test_case_click(self):
        self.driver.get('https://sahitest.com/demo/clicks.htm')
        # 单击操作
        ele_click = self.driver.find_element(By.XPATH, '//*[@type="button" and @value="click me"]')
        action = ActionChains(self.driver)
        action.click(ele_click)
        print('单击完成')

        # 右击操作
        ele_context_click = self.driver.find_element(By.XPATH, '//*[@type="button" and @value="right click me"]')
        action.context_click(ele_context_click)
        print('右击完成')

        # 双击操作
        ele_double_click = self.driver.find_element(By.XPATH, '//*[@type="button" and @value="dbl click me"]')
        action.double_click(ele_double_click)
        print('双击完成')
        action.perform()

    # 鼠标移动停放
    def test_move_to_element(self):
        self.driver.get('https://www.baidu.com')
        ele = self.driver.find_element(By.CSS_SELECTOR, '#s-usersetting-top')
        action = ActionChains(self.driver)
        action.move_to_element(ele)
        action.perform()

    # 鼠标拖拽
    def test_drag_drop(self):
        self.driver.get('https://sahitest.com/demo/dragDropMooTools.htm')
        ele = self.driver.find_element(By.XPATH, '//div[1]')
        ele1 = self.driver.find_element(By.XPATH, '//div[2]')
        action = ActionChains(self.driver)
        action.drag_and_drop(ele, ele1)
        # 按住第一个元素  释放第二个元素
        action.click_and_hold(ele).release(ele1).perform()
        # 点击并不放，移动到 第二个元素
        action.click_and_hold(ele).move_to_element(ele1).release().perform()
        action.perform()

    # 键盘输入   输入username Tom,然后在删除m
    def test_keys(self):
        self.driver.get('https://sahitest.com/demo/label.htm')
        ele = self.driver.find_element(By.XPATH, '//label/*[@type="textbox"]')
        ele.click()
        action = ActionChains(self.driver)
        # pause ： 等待1s
        # 键盘输入 username
        action.send_keys("username").pause(1)
        # 输入空格
        action.send_keys(Keys.SPACE).pause(1)
        # 输入 tom
        action.send_keys('tom').pause(1)
        # 删除 m
        action.send_keys(Keys.BACK_SPACE).pause(1)
        action.perform()
        time.sleep(3)


# ==========================================================================


# TouchAction：执行PC端和移动端的点击、拖拽、多点触控、以及模拟手势的各种操作
# TouchAction ：执行PC端、移动端和 H5页面 的点击、右击、双击、拖拽等

"""
tap: 点击
double_hold: 双击
tap_and_hold: 点击并不放
move: 手势移动指定偏移
release: 释放手势
scroll: 手势点击并滚动
scroll_from_element ： 从某一个元素，滚动到某一个坐标点
flick ： 滑动
flick_element ： 滑动到某一个元素  -> 支持坐标的偏移，以什么速度偏移
long_press: 常按
perform: 执行
"""


class TestTouchAction:
    def setup(self):
        # option = webdriver.ChromeOptions()
        # option.add_experimental_option('w3c',False)
        # self.driver = webdriver.Chrome(options=option)
        self.driver = webdriver.Chrome()
        self.driver.maximize_window()
        self.driver.implicitly_wait(10)

    def teardown(self):
        self.driver.quit()

    def test_touchaction_scrollbottom(self):
        # 1. 打开百度
        # 2. 输入 selenium测试
        # 3. 通过 TouchAction 方法 点击搜索框
        # 4. 滑动到底部，点击下一页
        # 5. 关闭 浏览器
        self.driver.get('https://www.baidu.com')
        ele_baidu = self.driver.find_element(By.ID, 'kw')
        # 在百度输入内容
        ele_baidu.send_keys('selenium测试')
        # 点击搜索按钮
        action = TouchActions(self.driver)
        ele_search = self.driver.find_element(By.ID, 'su')
        action.tap(ele_search)
        action.perform()
        # 滑动到底部
        action.scroll_from_element(ele_baidu, 0, 10000).perform()
        time.sleep(3)

        # 点击下一页
        self.driver.find_element(By.XPATH, '//*[@class="n"]').click()


"""
1.
什么是表单？
表单是一个包含表单元素的区域
表单元素是允许用户在表单中（比如：文本域，下拉框，单选框，复选框等）输入信息的元素
表单使用表单标签 < form > 定义。例如 ： < form > < input / > < / form >
2.
操作表单元素的步骤
首先要定位到表单
然后去操作元素（清空，输入或者点击等）
"""
# 表单操作 ： <form>
# 1、定位到表单元素   2、操作元素（清空、输入、点击）
"""
文本框
下拉框
单选框
复选框
"""


class Testform:
    def setup(self):
        self.driver = webdriver.Chrome()
        self.driver.maximize_window()
        self.driver.implicitly_wait(10)

    def teardown(self):
        self.driver.quit()

    def test_form(self):
        self.driver.get('http://testerhome.com/account/sign_in')
        # 登录
        self.driver.find_element(By.CSS_SELECTOR, "#user_login").send_keys('214829112@qq.com')
        self.driver.find_element(By.CSS_SELECTOR, "#user_password").send_keys('hogwarts')

        # 点击记住密码
        self.driver.find_element(By.ID, "user_remember_me").click()

        # 提交表单操作
        self.driver.find_element(By.XPATH, "//*[@type='submit']").click()
